import 'dart:convert';
import 'dart:io';

import 'package:beautiful_demo/common/beans/ws_bean.dart';
import 'package:beautiful_demo/common/manager/user.dart';
import 'package:beautiful_demo/config.dart';

class WebSocketManager {
  static final instance = WebSocketManager();
  WebSocket _websocket;
  final Map<String, Function(WsBean)> _listener = {};
  final List<Function> _connectListener=[];

  int connectNum=0;//重新连接次数记录
  Future connect() async {
    try {
      if(!UserManager.instance.isLogin) return;
      _websocket = await WebSocket.connect(
          'ws://${Config.domain}/ws/${UserManager.instance.data.id}');
      connectNum=0;
      _initListener();
      _websocket.pingInterval = const Duration(seconds: 10);
      _connectListener.forEach((element) {element();});
      _connectListener.clear();
    }catch(e) {
      print("连接失败");
      _websocket=null;
      if(connectNum<10){
          connectNum++;
        //3秒后重新连接
        Future.delayed(const Duration(milliseconds: 3000)).then((value) =>
            connect());
      }else {
        //15秒后重新连接
        Future.delayed(const Duration(milliseconds: 15000)).then((value) =>
            connect());
      }
    }
  }

  void _initListener() {
    _websocket.listen((event) {
      final json = const JsonDecoder().convert(event);
      final bean = WsBean(json);
      final key1 = bean.mold;
      final key2 = bean.mold + "&" + bean.id.toString();
      if (_listener.containsKey(key2)) {
        _listener[key2](bean);
      } else if (_listener.containsKey(key1)) {
        _listener[key1](bean);
      }
    },onDone: () async  {
      print('websocketDone');
      //websocket被杀。或者服务器断掉，重新连接
      _websocket=null;
      connectNum=0;
      if(!isResume){
        return;
      }
      Future.delayed(const Duration(milliseconds: 1000)).then((value) =>
          connect());
    },cancelOnError: true,onError: (object,stack){
      print('websocketError');
    });
  }

  bool isResume=false;
  void onResume(){
    isResume=true;
    if(_websocket==null){
      connectNum=0;
      connect();
    }
  }

  void onPause(){
    isResume=false;
  }



  WsBean sendValue(int id,int viewType,String value){

    final bean=WsBean(null);
    bean.mold=WsBean.chat;
    bean.id=id;
    bean.valueMold=viewType;
    bean.value=value;
    final json=const JsonEncoder().convert(bean.toJson());
    _websocket?.add(json);
    return bean;
  }

  void sendMold(String mold,{int id=0,String value=""}){
    if(_websocket==null){
      _connectListener.add((){
        sendMold(mold,id:id,value:value);
      });
      return;
    }
    final bean=WsBean(null);
    bean.mold=mold;
    bean.id=id;
    bean.valueMold=0;
    bean.value=value;
    final json=const JsonEncoder().convert(bean.toJson());
    _websocket?.add(json);

  }

  void addListener(String mold, Function(WsBean) listener, {String id}) {
    String key = mold;
    if (id != null) {
      key = mold + "&" + id;
    }
    _listener[key] = listener;
  }

  void removeListener(String mold,  {String id}) {
    String key = mold;
    if (id != null) {
      key = mold + "&" + id;
    }
    if (_listener.containsKey(key)) {
      _listener.remove(key);
    }
  }

  void disConnect() {
    _websocket?.close();
    _websocket=null;
  }
}
